home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TeX 1995 July
/
TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO
/
dviware
/
kyocera
/
dvi.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-10-01
|
18KB
|
703 lines
/* dvi.c The dvi reader for dvi printers.
* Copyright 1985 Massachusetts Institute of Technology.
* Author: cjl@oz
* Slightly changed by Kees Straatman (mcvax!guvaxin!kees) for Kyocera driver
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include "fonts.h"
#include "dev.h"
#include "util.h"
#include "dvi.h"
extern char *rindex();
extern char *mktemp();
extern long ftell();
#define DVI_STACK_SIZE 512 /* Maximum dvi stack size supported. */
#define NFONTDIR_MAX 16
#define MAXDRIFT 2
#ifndef PXLDIR
#define PXLDIR "/usr/lib/tex/pxlfonts"
#endif
/* Runtime parameters specified by user
*/
FILE *out = stdout;
FILE *in;
char *dirvec[NFONTDIR_MAX];
char *acctfile = (char *)0;
int npages = 0;
int dirveclen;
unsigned long devopts,fontopts;
/* Runtime parameters specified by the dvi file & the user
*/
char pre_comment[257];
long numerator,denominator,half_denominator,dvinum,dviden,dvimag;
long globalmag;
/* Runtime data structures
*/
char stdoutbuf[BUFSIZ];
long h_pix,v_pix,h,v,w,x,y,z,device_dpi,fntspc;
unsigned long fntvec[512],chrvec[512][4];
int stackptr,fntveclen;
long hstack[DVI_STACK_SIZE];
long h_pixstack[DVI_STACK_SIZE];
long vstack[DVI_STACK_SIZE];
long v_pixstack[DVI_STACK_SIZE];
long wstack[DVI_STACK_SIZE];
long xstack[DVI_STACK_SIZE];
long ystack[DVI_STACK_SIZE];
long zstack[DVI_STACK_SIZE];
/* Stack manipulation: push and pop
*/
push()
{
if (stackptr >= DVI_STACK_SIZE) croak("dvi stack overflow");
hstack[stackptr] = h;
h_pixstack[stackptr] = h_pix;
vstack[stackptr] = v;
v_pixstack[stackptr] = v_pix;
wstack[stackptr] = w;
xstack[stackptr] = x;
ystack[stackptr] = y;
zstack[stackptr] = z;
stackptr++;
}
pop()
{
if (stackptr <= 0) croak("dvi stack underflow");
stackptr--;
h = hstack[stackptr];
h_pix = h_pixstack[stackptr];
v = vstack[stackptr];
v_pix = v_pixstack[stackptr];
w = wstack[stackptr];
x = xstack[stackptr];
y = ystack[stackptr];
z = zstack[stackptr];
}
position()
{
register int dh = h_pix - (h * numerator + half_denominator) / denominator;
register int dv = v_pix - (v * numerator + half_denominator) / denominator;
if (dh > MAXDRIFT) h_pix -= MAXDRIFT;
else if (dh < -MAXDRIFT) h_pix += MAXDRIFT;
if (dv > MAXDRIFT) v_pix -= MAXDRIFT;
else if (dv < -MAXDRIFT) v_pix += MAXDRIFT;
dev_position(h_pix,v_pix);
}
/* Drawing: set and setrule
*/
set(ch,movep)
unsigned long ch;
int movep;
{
long texwidth,devwidth;
f_use_char(ch,&texwidth,&devwidth);
position();
f_setc(ch,devwidth);
if (movep) {
h += texwidth;
h_pix += devwidth;
}
}
setrule(movep)
int movep;
{
long a = sget4(in);
long b = sget4(in);
long a_pix,b_pix;
if (a > fntspc || a < -fntspc)
a_pix = ((v + a) * numerator + half_denominator) / denominator - v_pix;
else if (a < 0)
a_pix = - ((-a * numerator + half_denominator) / denominator);
else
a_pix = (a * numerator + half_denominator) / denominator;
if (b > fntspc || b < -fntspc)
b_pix = ((h + b) * numerator + half_denominator) / denominator - h_pix;
else if (b < 0)
b_pix = - ((-b * numerator + half_denominator) / denominator);
else
b_pix = (b * numerator + half_denominator) / denominator;
if (a_pix > 0 && b_pix > 0) {
position();
dev_draw_box(a_pix,b_pix);
}
if (movep) {
h += b;
h_pix += b_pix;
}
}
/* Movement: right and down
*/
right(dx)
long dx;
{
h += dx;
if (dx > fntspc || dx < -fntspc * 4)
h_pix = (h * numerator + half_denominator) / denominator;
else if (dx < 0)
h_pix -= (-dx * numerator + half_denominator) / denominator;
else
h_pix += (dx * numerator + half_denominator) / denominator;
}
down(dy)
long dy;
{
v += dy;
if (dy > fntspc * 5)
v_pix = (v * numerator + half_denominator) / denominator;
else if (dy < 0)
v_pix -= (-dy * numerator + half_denominator) / denominator;
else
v_pix += (dy * numerator + half_denominator) / denominator;
}
/* Special: xxx
*/
xxx(k)
long k;
{
position();
dev_special(k,in);
}
/* Fonts: fntdef
*/
fntdef(fontnum)
unsigned long fontnum;
{
unsigned long tfmchecksum = get4(in);
long s = sget4(in);
long d = sget4(in);
int a = get1(in);
int l = get1(in);
int i;
char area[257];
char name[257];
long mag;
for (i = 0; i < a; i++) area[i] = getc(in); area[a] = 0;
for (i = 0; i < l; i++) name[i] = getc(in); name[l] = 0;
mag = (long) (((double) s) * ((double) globalmag) / ((double) d));
debug("fntdef: num= %d area=\"%s\" name=\"%s\" mag=%d s=%d d=%d\n",
fontnum,area,name,mag,s,d);
f_define_font(fontnum,0,area,name,mag,s,tfmchecksum);
}
/* Fonts: fntdef
*/
nullfntdef(fontnum)
unsigned long fontnum;
{
register int a,l,i;
(void) getc(in); (void) getc(in); (void) getc(in); (void) getc(in);
(void) getc(in); (void) getc(in); (void) getc(in); (void) getc(in);
(void) getc(in); (void) getc(in); (void) getc(in); (void) getc(in);
a = getc(in);
l = getc(in);
for (i = 0; i < a; i++) (void) getc(in);
for (i = 0; i < l; i++) (void) getc(in);
}
/* Record this font number on fntvec
* We'll later pass fntvec to the fonts module
*/
int fntmark(fnt)
unsigned long fnt;
{
register int i;
for (i = 0; i < fntveclen; i++) if (fntvec[i] == fnt) return(i);
if (fntveclen >= sizeof(fntvec)) croak("too many fonts");
chrvec[fntveclen][0] = 0;
chrvec[fntveclen][1] = 0;
chrvec[fntveclen][2] = 0;
chrvec[fntveclen][3] = 0;
fntvec[fntveclen] = fnt;
return(fntveclen++);
}
chrmark(ch,i)
unsigned long ch;
int i;
{
chrvec[i][ch/32] |= (1 << (ch % 32));
}
/* End of page processing: eop
*/
eop()
{
dev_eop();
}
noprint_page(c,p)
long c[10];
long p;
{
int f;
register int ch;
(void) c; (void) p;
fntveclen = 0;
for (;;) {
if (ferror(in)) croak("noprint_page dvi input");
switch (ch = getc(in)) {
case SETRULE:
case PUTRULE:
(void) getc(in);
(void) getc(in);
(void) getc(in);
(void) getc(in);
case RIGHT4:
case W4:
case DOWN4:
case X4:
case Y4:
case Z4:
(void) getc(in);
case RIGHT3:
case W3:
case X3:
case DOWN3:
case Y3:
case Z3:
(void) getc(in);
case RIGHT2:
case W2:
case X2:
case DOWN2:
case Y2:
case Z2:
(void) getc(in);
case RIGHT1:
case W1:
case X1:
case DOWN1:
case Y1:
case Z1:
(void) getc(in);
case NOP:
case PUSH:
case POP:
case W0:
case X0:
case Y0:
case Z0:
break;
case EOP:
return;
case SET1:
case PUT1: chrmark(get1(in),f); break;
case SET2:
case PUT2: chrmark(get2(in),f); break;
case SET3:
case PUT3: chrmark(get3(in),f); break;
case SET4:
case PUT4: chrmark(get4(in),f); break;
case FNT1: f = fntmark(get1(in)); break;
case FNT2: f = fntmark(get2(in)); break;
case FNT3: f = fntmark(get3(in)); break;
case FNT4: f = fntmark(get4(in)); break;
case FNTDEF1: nullfntdef(get1(in)); break;
case FNTDEF2: nullfntdef(get2(in)); break;
case FNTDEF3: nullfntdef(get3(in)); break;
case FNTDEF4: nullfntdef(get4(in)); break;
case XXX1: swallow(get1(in),in); break;
case XXX2: swallow(get2(in),in); break;
case XXX3: swallow(get3(in),in); break;
case XXX4: swallow(get4(in),in); break;
case EOF:
croak("noprint_page EOF between BOP and EOP");
break;
default:
if (ch >= SETCHAR0 && ch <= SETCHAR127)
chrmark((unsigned long) (ch - SETCHAR0),f);
else if (ch >= FNTNUM0 && ch <= FNTNUM63)
f = fntmark((unsigned long) (ch - FNTNUM0));
else croak("noprint_page dvi command %d between BOP and EOP",ch);
break;
}
}
}
print_page(c,p)
long c[10];
long p;
{
long ch;
(void) p;
stackptr = 0;
h = v = w = x = y = z = h_pix = v_pix = 0;
position();
for (;;) {
if (ferror(in)) croak("print_page dvi input");
switch (ch = getc(in)) {
case EOF:
croak("print_page EOF between BOP and EOP");
break;
case SET1: set(get1(in),1); break;
case SET2: set(get2(in),1); break;
case SET3: set(get3(in),1); break;
case SET4: set(get4(in),1); break;
case SETRULE: setrule(1); break;
case PUT1: set(get1(in),0); break;
case PUT2: set(get2(in),0); break;
case PUT3: set(get3(in),0); break;
case PUT4: set(get4(in),0); break;
case PUTRULE: setrule(0); break;
case NOP: break;
case EOP: eop(); return;
case PUSH: push(); break;
case POP: pop(); break;
case RIGHT1: right(sget1(in)); break;
case RIGHT2: right(sget2(in)); break;
case RIGHT3: right(sget3(in)); break;
case RIGHT4: right(sget4(in)); break;
case W0: right(w); break;
case W1: right(w = sget1(in)); break;
case W2: right(w = sget2(in)); break;
case W3: right(w = sget3(in)); break;
case W4: right(w = sget4(in)); break;
case X0: right(x); break;
case X1: right(x = sget1(in)); break;
case X2: right(x = sget2(in)); break;
case X3: right(x = sget3(in)); break;
case X4: right(x = sget4(in)); break;
case DOWN1: down(sget1(in)); break;
case DOWN2: down(sget2(in)); break;
case DOWN3: down(sget3(in)); break;
case DOWN4: down(sget4(in)); break;
case Y0: down(y); break;
case Y1: down(y = sget1(in)); break;
case Y2: down(y = sget2(in)); break;
case Y3: down(y = sget3(in)); break;
case Y4: down(y = sget4(in)); break;
case Z0: down(z); break;
case Z1: down(z = sget1(in)); break;
case Z2: down(z = sget2(in)); break;
case Z3: down(z = sget3(in)); break;
case Z4: down(z = sget4(in)); break;
case FNT1: f_use_font(get1(in),&fntspc); break;
case FNT2: f_use_font(get2(in),&fntspc); break;
case FNT3: f_use_font(get3(in),&fntspc); break;
case FNT4: f_use_font(get4(in),&fntspc); break;
case FNTDEF1: nullfntdef(get1(in)); break;
case FNTDEF2: nullfntdef(get2(in)); break;
case FNTDEF3: nullfntdef(get3(in)); break;
case FNTDEF4: nullfntdef(get4(in)); break;
case XXX1: xxx(get1(in)); break;
case XXX2: xxx(get2(in)); break;
case XXX3: xxx(get3(in)); break;
case XXX4: xxx(get4(in)); break;
default:
if (ch >= SETCHAR0 && ch <= SETCHAR127)
set((unsigned long) (ch - SETCHAR0),1);
else if (ch >= FNTNUM0 && ch <= FNTNUM63)
f_use_font((unsigned long) (ch - FNTNUM0),&fntspc);
else croak("print_page dvi command %d between BOP and EOP",ch);
break;
}
}
}
/* Preamble processing.
*/
computescale()
{
double dd;
/* Compute scale factors for this file. */
globalmag = dvimag;
/* This is real hokey, but will probably work for TEX82. */
if (dvinum != 25400000 || dviden != 473628672) {
fprintf(stderr,"DVI file numerator and denominator weren't exactly ");
fprintf(stderr,"what was expected.\nScaling may be wrong.\n");
}
numerator = ((long) (((double) dvinum)
/ ((double) 254000)
/ ((double) 10)));
denominator = ((long) (((double) dviden)
/ ((double) globalmag)
* ((double) 1000)
/ ((double) device_dpi)
/ ((double) 10)));
half_denominator = denominator / 2;
debug("Computescale: globalmag=%d numerator=%d denominator=%d\n",
globalmag,numerator,denominator);
}
preamble()
{
int i = getc(in);
int k;
dvinum = get4(in);
dviden = get4(in);
dvimag = get4(in);
k = get1(in);
if (i != 2) croak("id_byte=%d, probably not a dvi file",i);
for (i = 0; i < k; i++) pre_comment[i] = getc(in);
pre_comment[k] = '\0';
computescale();
debug("Preamble: dvinum=%d dviden=%d dvimag=%d\n",
dvinum,dviden,dvimag);
debug(" comment: \"%s\"\n",pre_comment);
}
/* Beginning of page processing
*/
bop()
{
int i;
long c[10];
long p,fpos;
for (i = 0; i < 10; i++) c[i] = sget4(in);
p = sget4(in);
debug("first pass of page %d\n",c[0]);
fpos = ftell(in); /* Remember where we are */
noprint_page(c,p); /* First pass noprint to get fntvec */
/* Tell font module about the fonts */
f_newpage(fntvec,chrvec,fntveclen);
debug("second pass of page %d\n",c[0]);
fseek(in,fpos,0); /* Back up */
print_page(c,p); /* And finally do the page */
debug("done with page %d\n",c[0]);
npages++;
}
file_term()
{
f_term();
close_ef();
dev_term();
}
/* Postamble processing.
*/
find_postamble()
{
int ch;
long i = -4;
long q;
do (void) fseek(in,i--,2); while ((ch = getc(in)) == TRAILER);
if (ch != 2) croak("postamble id_byte=%d, probably not a dvi file",ch);
(void) fseek(in,i-4,2);
if ((ch = getc(in)) != POSTPOST) croak("no POSTPOST where expected");
q = sget4(in);
(void) fseek(in,q,0);
if ((ch = getc(in)) != POST) croak("no POST where expected");
}
postamble()
{
int ch;
long p = sget4(in);
unsigned long l,u,maxstackdepth,npages;
dvinum = get4(in);
dviden = get4(in);
dvimag = get4(in);
computescale();
l = get4(in);
u = get4(in);
maxstackdepth = get2(in);
npages = get2(in);
debug("Postamble: dvinum=%d dviden=%d dvimag=%d maxstackdepth=%d\n",
dvinum,dviden,dvimag,maxstackdepth);
debug(" npages=%d\n",npages);
if (maxstackdepth > DVI_STACK_SIZE)
croak("dvi file has too much stack depth");
f_init(out,pgmnam,dirvec,dirveclen,numerator
,denominator,globalmag,fontopts);
signal(SIGINT, file_term);
for (;;) {
if (ferror(in)) croak("postamble input");
switch (ch = getc(in)) {
case EOF:
croak("EOF found before POSTPOST");
break;
case FNTDEF1: fntdef(get1(in)); break;
case FNTDEF2: fntdef(get2(in)); break;
case FNTDEF3: fntdef(get3(in)); break;
case FNTDEF4: fntdef(get4(in)); break;
case NOP: break;
case POSTPOST: return;
default:
croak("dvi command %d in postamble",ch);
break;
}
}
}
/* Process a dvi file
*/
file_init()
{
int ch;
if ((ch = getc(in)) != PRE)
croak("first char %d not PRE, probably not a dvi file",ch);
find_postamble();
dev_init(out,devopts,&device_dpi);
open_ef();
postamble();
(void) fseek(in,1L,0);
preamble();
}
dvi_file()
{
int ch;
if (!dirveclen) dirvec[dirveclen++] = PXLDIR;
file_init();
for (;;) {
if (ferror(in)) croak("dvi_file input");
switch (ch = getc(in)) {
case EOF:
croak("EOF found between pages");
break;
case BOP: bop(); break;
case POST: file_term(); return;
case FNTDEF1: fntdef(get1(in)); break;
case FNTDEF2: fntdef(get2(in)); break;
case FNTDEF3: fntdef(get3(in)); break;
case FNTDEF4: fntdef(get4(in)); break;
case NOP: break;
default:
croak("dvi command %d between pages",ch);
break;
}
}
}
process_stdin()
{
int ch;
FILE *tf;
char tfn[257];
struct stat st;
if (fstat(fileno(stdin),&st) < 0) croak("can't stat stdin");
if ((st.st_mode & S_IFMT) == S_IFREG) {
in = stdin; infname = "stdin";
dvi_file();
in = NULL; infname = NULL;
} else {
/* Copy the dvi data to a temp file, since we have to do disk seeks. */
(void) sprintf(tfn,"/usr/tmp/%s.XXXXXX",pgmnam);
if (!(tf = fopen(mktemp(tfn),"w"))) croak("couldn't open %s",tfn);
unlink(tfn);
while (!ferror(stdin) && (ch = getchar()) != EOF) putc(ch,tf);
if (ferror(stdin)) croak("error on stdin");
(void) fseek(tf,0L,0);
infname = tfn; in = tf;
dvi_file();
in = NULL; infname = NULL;
(void) fclose(tf);
}
}
account()
{
FILE *acctf;
if (user && acctfile && access(acctfile, 02) >= 0 &&
((acctf = fopen(acctfile, "a")) != NULL)) {
fprintf(acctf, "%-5d\t%s:%s\n", npages, host, user);
fclose(acctf);
}
}
main(argc,argv)
int argc;
char *argv[];
{
FILE *f;
int nfiles = 0;
int i;
setbuf(stdout,stdoutbuf);
pgmnam = argv[0];
fontopts = 0;
devopts = 0;
for (i = 1; i < argc; i++)
if (argv[i][0] == '-') switch(argv[i][1]) {
case 'd':
debugging++;
break;
case 'h':
host = argv[++i];
break;
case 'n':
user = argv[++i];
break;
case 'x':
case 'y':
break;
default:
croak("bad switch: %s",argv[i]);
break;
} else
acctfile = argv[i];
process_stdin();
account();
exit(0);
}